#ifndef _QUEUE_
#define _QUEUE_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define Queue(T) T##_Queue
#define List(T) T##_List
typedef struct Queue(T) Queue(T);


#define SET_QUEUE_TYPE(T)        \
typedef struct List(T) {         \
	T *e;                        \
	struct List(T)* pre;         \
	struct List(T)* next;        \
}List(T);                        \
typedef struct {                 \
	void (*DestroyQueue)();      \
	void (*ClearQueue)();        \
	int (*QueueEmpty)();         \
	int (*QueueLength)();        \
	T (*GetHead)();              \
	void (*EnQueue)(T );         \
	T (*DeQueue)();              \
	List(T)* (*begin)();         \
	List(T)* (*end)();           \
}Queue(T);


#define FUNCTION_BADY(T)         \
void DestroyQueue(){             \
	List(T)* temp;               \
	while(my_first){             \
		temp = my_first;         \
		my_first = my_first->next; \
		free(temp);              \
	}                            \
}                                \
void ClearQueue(){               \
	while(my_last != my_first) { \
		my_last = my_last->pre;   \
	}                            \
	length = 0;                  \
}                                \
int QueueEmpty() {               \
	return length == 0;          \
}                                \
int QueueLength() {              \
	return length;               \
}                                \
T GetHead() {                    \
    if(length == 0) exit(0);     \
	return (T)my_first->e;       \
}                                \
void EnQueue(T e) {              \
	if(!my_first){               \
		my_first = (List(T)*)malloc(sizeof(List(T)));\
		my_first->pre = my_first->next = NULL;\
		my_first->e = e;         \
        my_first->next = my_last;\
	} else {                     \
		if(!my_last){            \
			my_last = (List(T)*)malloc(sizeof(List(T)));\
			my_last->next = NULL;\
		}                        \
		my_last->e = e;          \
		my_last = my_last->next; \
	}                            \
	length ++;                   \
}                                \
T DeQueue() {                    \
	if(length == 0) exit(0);     \
	T tmp = my_first->e;         \
	List(T)* temp = my_first;    \
	my_first = my_first->next;   \
	free(temp);                  \
	if(!my_first) my_first =my_last = NULL;\
	else my_first->pre = NULL;   \
    length--;                    \
	return tmp;                  \
}                                \
List(T)* begin() {               \
	return my_first;             \
}                                \
List(T)* end() {                 \
	return my_last;              \
}                                \






#define ASSIGN_FUNCTION          \
this.DestroyQueue = DestroyQueue;\
this.ClearQueue = ClearQueue;    \
this.QueueEmpty = QueueEmpty;    \
this.QueueLength = QueueLength;  \
this.GetHead = GetHead;          \
this.EnQueue = EnQueue;          \
this.DeQueue = DeQueue;          \
this.begin = begin;              \
this.end = end;                  \



#define InitQueue(T)             \
({                               \
	List(T) *my_first = NULL;    \
	List(T) *my_last = NULL;     \
	int length = 0;              \
	Queue(T) this;               \
	FUNCTION_BADY(T)             \
	ASSIGN_FUNCTION              \
	this;                        \
})

#endif
